﻿using HCMS.EntityFrameworkCore;
using HCMS.Extensions;
using HCMS.HttpApi.Site.Filter;
using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;

namespace HCMS.HttpApi.Site
{
    /// <summary>
    /// Abp 框架 模块加载 类
    /// </summary>
    [DependsOn(
        typeof(HCMSApplicationModule),
        typeof(HCMSApplicationContractsModule),
        typeof(HCMSEntityFrameworkCoreModule),
        typeof(AbpAutofacModule),
        typeof(HCMSDomainSharedModule)
    //typeof(AbpSwashbuckleModule)
    //typeof(HCMSHttpApiModule)
    )]
    public class HCMSHttpApiSiteModule : AbpModule
    {
        /// <summary>
        /// 预加载 服务配置
        /// </summary>
        /// <param name="context"></param>
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {

        }

        /// <summary>
        /// 服务配置
        /// </summary>
        /// <param name="context"></param>
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration = context.Services.GetConfiguration();

            ConfigureAutoApiControllers();
            ConfigureSwaggerServices(context.Services);
        }

        /// <summary>
        /// 配置 API 控制器 所在项目，并将相应的控制器公开
        /// </summary>
        private void ConfigureAutoApiControllers()
        {
            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                options
                    .ConventionalControllers
                    .Create(typeof(HCMSHttpApiSiteModule).Assembly);
            });
        }

        /// <summary>
        /// 配置 Swagger
        /// </summary>
        /// <param name="services"></param>
        private void ConfigureSwaggerServices(IServiceCollection services)
        {
            services.AddAbpSwaggerGen(
                options =>
                {
                    #region 描述、说明

                    {   // 授权认证 API
                        var description = new List<string>() {
                            "access_token 是 api 接口调用凭据，为了保证接口的安全性，access_token 有效期为一个月。",
                        };

                        options.SwaggerDoc("oauth2", new OpenApiInfo
                        {
                            Title = "OAuth 2.0 认证",
                            Version = "v1",
                            Description = string.Join("<br />", description)
                        });
                    }

                    {
                        // 公开接口
                        var description = new List<string>() {
                            "业务相关 API",
                            "access_token 是 api 接口调用凭据，为了保证接口的安全性，access_token 有效期为一个月。",
                            "如果过期可以调用【OAuth2】相关方法重新获取。",
                            "注意：调用接口，access_token 参数必须以 QueryString 的形式写在 URL 中"
                        };

                        options.SwaggerDoc("open-api", new OpenApiInfo
                        {
                            Title = "业务 API",
                            Version = "v1",
                            Description = string.Join("<br />", description)
                        });
                    }

                    // 对接口进行分组展示
                    options.DocInclusionPredicate((docName, apiDes) =>
                    {
                        if (!apiDes.TryGetMethodInfo(out MethodInfo method))
                            return false;
                        var version = method.DeclaringType.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
                        if (docName == "v1" && !version.Any())
                            return true;
                        var actionVersion = method.GetCustomAttributes(true).OfType<ApiExplorerSettingsAttribute>().Select(m => m.GroupName);
                        if (actionVersion.Any())
                            return actionVersion.Any(v => v == docName);
                        return version.Any(v => v == docName);
                    });
                    options.CustomSchemaIds(type => type.FullName);
                    #endregion

                    #region 注释展示
                    //--- 设置 XML 注释路径 ---
                    // 【设置后，文档可以看到具体的中文注释信息】
                    // 项目属性 → 生成 → 输出 → 文档文件【这个也要勾选上，xml 描述文件才会生成】
                    {
                        // 当前 接口项目 文档
                        var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                        options.IncludeXmlComments(xmlPath);
                    }

                    {
                        // HCMS.Domain.Shared 项目 文档
                        // 公共模块 在这个项目
                        var assembly = typeof(HCMSDomainSharedModule).Assembly;
                        var basePath = assembly.Location.Substring(0, assembly.Location.LastIndexOf("\\") + 1);

                        var xmlFile = $"{assembly.GetName().Name}.xml";
                        var xmlPath = Path.Combine(basePath, xmlFile);
                        options.IncludeXmlComments(xmlPath);
                    }

                    {
                        // HCMS.Application.Contracts 项目 文档
                        // Dto 在这个项目
                        var assembly = typeof(HCMSApplicationContractsModule).Assembly;
                        var basePath = assembly.Location.Substring(0, assembly.Location.LastIndexOf("\\") + 1);

                        var xmlFile = $"{assembly.GetName().Name}.xml";
                        var xmlPath = Path.Combine(basePath, xmlFile);
                        options.IncludeXmlComments(xmlPath);
                    }
                    #endregion

                    #region open-api 需要传入 AccessToken 请求参数
                    options.OperationFilter<AddCommonParametersOperationFilter>();
                    #endregion

                    // 隐藏 ABP 默认终端节点
                    options.HideAbpEndpoints();

                    // 隐藏 ABP 框架自动生成的 schemas
                    options.SchemaFilter<HideAbpSchemaFilter>();
                }
            );
        }
    }
}
